package geppetto.cat.analysis;

import geppetto.cat.alignments.Alignment;
import geppetto.cat.common.Pair;
import geppetto.cat.corpus.BilingualCorpus;
import gnu.trove.TIntArrayList;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;



public class ErrorAnalysis {

	BilingualCorpus _corpus;

	public ErrorAnalysis(BilingualCorpus corpus) {
		_corpus = corpus;
	}

	public AllErrors commonErrors(ArrayList<Alignment> predicted,
			ArrayList<Alignment> gold, BilingualCorpus corpus,
			ArrayList<Pair<Integer, Integer>> mask) {

		AllErrors errors = new AllErrors(predicted.size());

		/*
		 * for(int i=0; i < predicted.size(); i++){ //System.out.println("Frase
		 * n " + i); errors.addSentenceError(i,
		 * calculateSentenceErrors(predicted.get(i),gold.get(i),corpus)); }
		 */
		lonelyPoints(predicted, gold, mask);
		return errors;
	}

	// Return total number of null aligned words and
	// total number of foreign words
	public int[] nullAlignedWords(ArrayList<Alignment> predicted) {
		int[] points = new int[2];
		for (int i = 0; i < predicted.size(); i++) {
			Alignment p = predicted.get(i);
			points[0] += p.getNumberNulls();
			points[1] += p.getForeignLenght();
			// System.out.println("Sentence " + i + " null " +
			// p.getNumberNulls() + " words " + p.getForeignLenght());
		}
		return points;
	}

	public int[] lonelyPoints(ArrayList<Alignment> predicted,
			ArrayList<Alignment> gold, ArrayList<Pair<Integer, Integer>> mask) {
		int[] points = new int[2];
		for (int i = 0; i < predicted.size(); i++) {
			Alignment p = predicted.get(i);
			Alignment g = gold.get(i);
			int[] pointsLocal = p.getLonelyPoints(g, mask);
			points[0] += pointsLocal[0];
			points[1] += pointsLocal[1];
			// System.out.println("Sentence number" + i +" Correct " +
			// pointsLocal[0] + "Incorrect " + pointsLocal[1]);
		}
		System.out.println("Total Correct " + points[0] + "Incorrect "
				+ points[1]);
		return points;
	}

	public SentenceErrors calculateSentenceErrors(Alignment predicted,
			Alignment gold, BilingualCorpus corpus) {
		SentenceErrors errors = new SentenceErrors(predicted
				.getSentenceNumber(), predicted.getSentenceSource(), predicted
				.getForeignLenght());
		// System.out.println(predicted.getForeignLenght() + " " +
		// predicted.getSourceLenght());
		// System.out.println(gold.getForeignLenght() + " " +
		// gold.getSourceLenght());
		for (int i = 0; i < predicted.getForeignLenght(); i++) {
			for (int j = 0; j < predicted.getSourceLenght(); j++) {
				if (predicted.hasPosition(j, i) && gold.hasPosition(j, i)) {
					// System.out.println("Correcto");
				} else if (predicted.hasPosition(j, i)) {
					TIntArrayList surePositions = gold.getSurePosition(i);
					TIntArrayList possiblePositions = gold
							.getPossiblePosition(i);
					TIntArrayList sure = gold.getSurePosition(i);
					TIntArrayList possible = gold.getPossiblePosition(i);
					errors.addError(i, new AlignmentError(corpus
							.getForeignWordId(predicted.getSentenceNumber(),
									predicted.getSentenceSource(), i), i,
							corpus.getSourceWordId(predicted
									.getSentenceNumber(), predicted
									.getSentenceSource(), j), j, sure,
							surePositions, possible, possiblePositions));
				} else if (gold.hasPosition(j, i)) {
					TIntArrayList surePositions = gold.getSurePosition(i);
					TIntArrayList possiblePositions = gold
							.getPossiblePosition(i);
					TIntArrayList sure = gold.getSurePosition(i);
					TIntArrayList possible = gold.getPossiblePosition(i);
					errors.addError(i, new AlignmentError(corpus
							.getForeignWordId(predicted.getSentenceNumber(),
									predicted.getSentenceSource(), i), i, -1,
							-1, sure, surePositions, possible,
							possiblePositions));
				} else {
					// System.out.println("ok");
				}
			}
		}
		return errors;
	}

	/*
	 * public allErrors collectErrors(String predictionName, BilingualCorpus2
	 * corpus) throws IOException{ ArrayList<Alignment2> predicted =
	 * readAlignments(predictionName, corpus); ArrayList<Alignment2> gold =
	 * corpus.getGold().getAlignments(); commonErrors(predicted, gold, corpus); }
	 */

	public void analisyPrediction(String predictionName,
			BilingualCorpus corpus, PrintStream out) throws IOException {
		ArrayList<Alignment> predicted = readAlignments(predictionName, corpus);
		// ArrayList<Alignment> gold = corpus.getGold().getAlignments();
		/*
		 * ArrayList<Pair<Integer,Integer>> mask = new ArrayList<Pair<Integer,Integer>>();
		 * mask.add(new Pair<Integer,Integer>(-1,-1)); mask.add(new Pair<Integer,Integer>(-1,0));
		 * mask.add(new Pair<Integer,Integer>(0,-1)); mask.add(new Pair<Integer,Integer>(0,1));
		 * mask.add(new Pair<Integer,Integer>(1,0)); mask.add(new Pair<Integer,Integer>(1,1));
		 * mask.add(new Pair<Integer,Integer>(-1,1)); mask.add(new Pair<Integer,Integer>(1,-1));
		 */
		// AllErrors errors = commonErrors(predicted, gold, corpus, mask);
		// errors.output(corpus, out);
		int[] points = nullAlignedWords(predicted);
		double number = points[0] * 1.0 / points[1];
		System.out.println("Number of null words " + points[0]
				+ " Number of words " + points[1] + "% " + number);

	}

	public ArrayList<Alignment> readAlignments(String fileName,
			BilingualCorpus corpus) throws IOException {
		byte sentenceSource = BilingualCorpus.TEST_CORPUS;
		ArrayList<Alignment> al = new ArrayList<Alignment>();
		Alignment gold = null;
		int sentenceNumber = 0;
		int number;
		BufferedReader input = new BufferedReader(new InputStreamReader(
				new FileInputStream(fileName)));
		String line = input.readLine();
		while ((line != null)) {
			String[] fields = line.split(" ");
			number = Integer.parseInt(fields[0]);
			if (number != sentenceNumber) {
				// System.out.println("Reading new line");
				if (gold != null) {
					al.add(gold);
				}
				sentenceNumber = number;
				// System.out.println("SentenceNumber" + (sentenceNumber-1) + "
				// " + corpus.getSourceSentenceLength(sentenceNumber-1 ,
				// sentenceSource)+ " " +
				// corpus.getForeignSentenceLength(sentenceNumber-1,
				// sentenceSource));
				gold = new Alignment(sentenceNumber - 1, sentenceSource, corpus
						.getSourceSentenceLength(sentenceNumber - 1,
								sentenceSource), corpus
						.getForeignSentenceLength(sentenceNumber - 1,
								sentenceSource));
			}
			int sindex = Integer.parseInt(fields[1]);
			int findex = Integer.parseInt(fields[2]);
			byte type;
			// If there is no field aligment is Sure (according to EPPS)
			if (fields.length == 4 && fields[3].equals("P"))
				type = 1;
			else
				type = 2;
			// System.out.print(corpus.getSourceWord((sentenceNumber-1),
			// sentenceSource, sindex-1) +" ");
			// System.out.println(corpus.getForeignWord((sentenceNumber-1),
			// sentenceSource, findex-1) + "\n");
			// System.out.println((sentenceNumber-1) + "sIndex " + sindex + "
			// fIndex " + findex +" type " + type);
			gold.add(sindex - 1, findex - 1, type);
			line = input.readLine();
		}
		al.add(gold); // Catch last alignment
		return al;
	}

	public void outputAligmentLatex(String alignmentFile, int aligmentNumber,
			String outputFile, BilingualCorpus corpus) throws IOException {
		Alignment predicted = readAlignments(alignmentFile, corpus).get(
				aligmentNumber);
		Alignment gold = corpus.getGold().getAlignments().get(aligmentNumber);
		/*
		 * PrintStream examples = new PrintStream(new
		 * FileOutputStream(outputFile),true,"ISO8859_1");
		 * examples.println("%-*-coding: iso-latin-1 -*-");
		 * examples.println("\\documentclass{article}");
		 * examples.println("\\usepackage{isolatin1}");
		 * examples.println("\\usepackage{amsmath}");
		 * examples.println("\\usepackage{rotating}");
		 * examples.println("\\newcommand{\\egwf
		 * }[1]{\\multicolumn{1}{c}{\\begin{rotate}{-30}{#1}\\end{rotate}} }");
		 * examples.println("\\begin{document}");
		 * examples.println("\\begin{flushleft}");
		 * AlignerOutputLatex.outputWithGoldLatex(predicted, gold, corpus,
		 * examples, Integer.MAX_VALUE); examples.println("\\end{flushleft}");
		 * examples.println("\\end{document}");
		 */
	}

	// public static void main(String[] args) throws IOException {
	// String corpusName = args[0];
	// int size = Integer.parseInt(args[1]);
	// int maxSentenceSize = Integer.parseInt(args[2]);
	// String dir = args[3];
	// String modelName = args[4];
	// System.out.println("baseline experiment: ");
	// System.out.println("Corpus "+corpusName);
	// System.out.println("Size "+size);
	// System.out.println("Max Sentence size "+maxSentenceSize);
	// System.out.println("ModelDir "+dir);
	// System.out.println("Model Name "+modelName);
	// System.out.println("---");
	// Corpora.Cpr2 c = new Corpora.Cpr2(corpusName, size,maxSentenceSize);
	// BilingualCorpus corpus = c.bi;
	// String directory = dir +modelName+"/"+corpusName+"/"+size+"/";
	//		
	// ErrorAnalysis er = new ErrorAnalysis(corpus);
	//		
	//		
	// String alignmentFile =directory+"align_upf-M1.txt";
	// er.analisyPrediction(alignmentFile, corpus, System.out);
	//		
	// alignmentFile =directory+"align_upf-M2.txt";
	// er.analisyPrediction(alignmentFile, corpus, System.out);
	//		
	// alignmentFile =directory+"align_uvf-Mhmm.txt";
	// er.analisyPrediction(alignmentFile, corpus, System.out);
	//		
	//		
	// /*
	// int alignmentNumber = 100;
	// String model = "Baseline";
	// String inputFile =
	// "/afs/l2f/home/javg/word-alignments/outputs/Baseline/hansardslx/10000/alignments/align_upf-mhmm.txt";
	// System.out.println(inputFile);
	// //er.analisyPrediction("/afs/l2f/home/javg/word-alignments/outputs/Bistochastic/eppslx/100000/alignments/align_upi-mhmm.txt",
	// corpus);
	// er.outputAligmentLatex(inputFile ,
	// alignmentNumber,
	// "/afs/l2f/home/javg/word-alignments/outputs/tex/"+model+"-hansards-10000-"+alignmentNumber+".tex",
	// corpus);
	// inputFile =
	// "/afs/l2f/home/javg/word-alignments/outputs/Bistochastic/hansardslx/10000/alignments/align_upf-mhmm.txt";
	// model = "Bistochastic";
	// er.outputAligmentLatex(inputFile,
	// alignmentNumber,
	// "/afs/l2f/home/javg/word-alignments/outputs/tex/"+model+"-hansardslx-10000-"+alignmentNumber+".tex",
	// corpus);
	// */
	// }
}
